package org.kth.dks.dks_dht;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.kth.dks.DKSObject;
import org.kth.dks.dks_marshal.DKSMessage;
import org.kth.dks.dks_node.Interval;

public class ReplicateMsg extends DKSMessage {
    public final static String NAME= "REPLICATEMSG";

    private List tripletEntries = null;
    private List intervals = null;

    private ReplicationType replicationType;

    public String getName() { return NAME; }
    public List getTripletList() { return tripletEntries; }
    public List getIntervals() { return intervals; }
    public ReplicationType getReplicationType() { return replicationType; }

    public  ReplicateMsg() {
    }

    public  ReplicateMsg(List te, List in, ReplicationType type) {
	this.tripletEntries  = te;
	this.replicationType = type;
	this.intervals       = in;
    }

    public static class ReplicationType {
      public static final ReplicationType JOIN = new ReplicationType("JOIN");
      public static final ReplicationType LEAVE = new ReplicationType("LEAVE");
      private String name;
      public ReplicationType(String a) { this.name=a; }
      public String toString() { return name; }
      public static ReplicationType valueOf(String a) {
        if (a.equals(LEAVE.toString())) return LEAVE;
        else if (a.equals(JOIN.toString())) return JOIN;
        else return null;
      }
    }

    public void marshal() throws IOException {
	marshaler.addString(replicationType.toString(), "reptype");
	marshaler.addInt(tripletEntries.size(), "tripsize");
	int cnt = 1;
	for (Iterator it = tripletEntries.iterator(); it.hasNext();) {
	    StoreTriplet curr = (StoreTriplet) it.next();
	    marshaler.addLong(curr.key.longValue(), "key"+cnt);
	    marshaler.addInt(curr.index, "ind"+cnt);
	    marshaler.addDKSObject(curr.obj, "obj"+cnt);
	    cnt++;
	}

	marshaler.addInt(intervals.size(), "intervalsize");
	cnt = 1;
	for(Iterator iter2 = intervals.iterator(); iter2.hasNext();){
	    Interval in = (Interval) iter2.next();
	    marshaler.addLong(in.start, "start"+cnt);
	    marshaler.addLong(in.end, "end"+cnt);
            cnt++;
	}
    }

    public void unmarshal() throws IOException {
	replicationType = ReplicationType.valueOf( marshaler.remString("reptype") );
	int sz = marshaler.remInt("tripsize");
	tripletEntries = new ArrayList();
	for (int cnt = 1; cnt<=sz; cnt++) {
	    long k      = marshaler.remLong("key"+cnt);
	    int i       = marshaler.remInt("ind"+cnt);
	    DKSObject o = marshaler.remDKSObject("obj"+cnt);
	    tripletEntries.add( new StoreTriplet(i, new Long(k), o));
	}

	sz = marshaler.remInt("intervalsize");
	intervals = new ArrayList();
	for (int cnt = 1; cnt<=sz; cnt++) {
	    long start      = marshaler.remLong("start"+cnt);
	    long end       =  marshaler.remLong("end"+cnt);
	    intervals.add(new Interval(start, end));
	}
    }
}

